/*
 * 
 *
 *
 */
package com.hboxs.asl.dao.impl;

import com.hboxs.asl.Page;
import com.hboxs.asl.Pageable;
import com.hboxs.asl.dao.CourseTradeDao;
import com.hboxs.asl.entity.CourseTrade;
import com.hboxs.asl.entity.Member;
import org.springframework.stereotype.Repository;

import javax.persistence.FlushModeType;
import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 * Dao - 课程流水
 */
@Repository("courseTradeDaoImpl")
public class CourseTradeDaoImpl extends BaseDaoImpl<CourseTrade, Long> implements CourseTradeDao {

    @Override
    public CourseTrade findBySn(String sn) {
        if (sn == null) {
            return null;
        }
        String jpql = "select courseTrades from CourseTrade courseTrades where lower(courseTrades.sn) = lower(:sn)";
        try {
            return entityManager.createQuery(jpql, CourseTrade.class).setFlushMode(FlushModeType.COMMIT).setParameter("sn", sn).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Override
    public Page<CourseTrade> all(Pageable pageable, Member member, CourseTrade.CourseType courseType, CourseTrade.PaymentStatus paymentStatus) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (member != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), member));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        if (courseType != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("courseType"), courseType));
        }
        restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("hasReview"), true));
        criteriaQuery.where(restrictions);
        criteriaQuery.orderBy(criteriaBuilder.asc(root.get("createDate")));
        return super.findPage(criteriaQuery, pageable);
    }

    @Override
    public Page<CourseTrade> allTrade(Pageable pageable, Member member, CourseTrade.PaymentStatus paymentStatus) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (member != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), member));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        criteriaQuery.where(restrictions);
        criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createDate")));
        return super.findPage(criteriaQuery, pageable);
    }

    @Override
    public Page<CourseTrade> ing(Pageable pageable, Member member, CourseTrade.CourseType courseType, CourseTrade.PaymentStatus paymentStatus) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (member != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), member));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        if (courseType != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.notEqual(root.get("courseType"), courseType));
        }
        criteriaQuery.where(restrictions);
        criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createDate")));
        return super.findPage(criteriaQuery, pageable);
    }

    @Override
    public Page<CourseTrade> toEvaluate(Pageable pageable, Member member, CourseTrade.CourseType courseType, CourseTrade.PaymentStatus paymentStatus, Boolean hasReview) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (member != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), member));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        if (courseType != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("courseType"), courseType));
        }
        if (hasReview != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("hasReview"), hasReview));
        }
        criteriaQuery.where(restrictions);
        criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createDate")));
        return super.findPage(criteriaQuery, pageable);
    }

    @Override
    public long findPaidCourse(Long courseId, Member buyer, CourseTrade.PaymentStatus paymentStatus) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (courseId != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("courseId"), courseId));
        }
        if (buyer != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), buyer));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        criteriaQuery.where(restrictions);
        return super.count(criteriaQuery, null);
    }

    @Override
    public Page<CourseTrade> findPaidCourseTrades(Pageable pageable, Member buyer, CourseTrade.PaymentStatus paymentStatus, Long categoryId) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        if (buyer != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("buyer"), buyer));
        }
        if (paymentStatus != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        }
        if (categoryId != null) {
            restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("categoryId"), categoryId));
        }
        criteriaQuery.where(restrictions);
        criteriaQuery.orderBy(criteriaBuilder.asc(root.get("createDate")));
        return super.findPage(criteriaQuery, pageable);
    }

    @Override
    public long getCourseTradeCount(CourseTrade.PaymentStatus paymentStatus) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<CourseTrade> criteriaQuery = criteriaBuilder.createQuery(CourseTrade.class);
        Root<CourseTrade> root = criteriaQuery.from(CourseTrade.class);
        criteriaQuery.select(root);
        Predicate restrictions = criteriaBuilder.conjunction();
        restrictions = criteriaBuilder.and(restrictions, criteriaBuilder.equal(root.get("paymentStatus"), paymentStatus));
        criteriaQuery.where(restrictions);
        return super.count(criteriaQuery, null);
    }

    @Override
    public CourseTrade courseTradeCount(CourseTrade.PaymentStatus paymentStatus, Member member, Long courseId) {

        String jpql = "select courseTrade from CourseTrade courseTrade where courseTrade.courseId = :courseId and courseTrade.buyer = :buyer and " +
                "courseTrade.paymentStatus = :paymentStatus";
        try {
            return entityManager.createQuery(jpql, CourseTrade.class).setFlushMode(FlushModeType.COMMIT).setParameter("courseId", courseId)
                    .setParameter("buyer", member).setParameter("paymentStatus", paymentStatus).getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    @Override
    public void updateBatch(Long courseId, CourseTrade.CourseType courseType) {
        String jpql = "update CourseTrade courseTrade set courseTrade.courseType = :courseType  where courseTrade.courseId = :courseId";
        try {
            entityManager.createQuery(jpql).setFlushMode(FlushModeType.COMMIT).setParameter("courseType", courseType).setParameter("courseId", courseId).executeUpdate();
        } catch (NoResultException e) {
            e.printStackTrace();
        }
    }

}
